// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Microsoft.Toolkit.Uwp;
using Microsoft.Toolkit.Uwp.UI;
using Microsoft.Toolkit.Uwp.UI.Controls;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;

namespace UnitTests.UWP.UI.Controls
{
    [TestClass]
    public class Test_ImageEx : VisualUITestBase
    {
        private const string ImageString = "";

        [TestMethod]
        public async Task SetSourceToOpenedBitmapImage()
        {
            await App.DispatcherQueue.EnqueueAsync(async () =>
            {
                var bitmapImage = new BitmapImage();

                using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(@"UnitTests.UWP.Assets.StoreLogo.embeded.png");
                using var memStream = new MemoryStream();
                await stream.CopyToAsync(memStream);
                memStream.Seek(0, SeekOrigin.Begin);
                await bitmapImage.SetSourceAsync(memStream.AsRandomAccessStream());

                var imageLoader = new ImageEx();

                await SetTestContentAsync(imageLoader);

                Assert.AreEqual("Unloaded", GetCurrentState(imageLoader));

                var imageOpendedCallCount = 0;

                imageLoader.ImageExOpened += (s, e) =>
                {
                    imageOpendedCallCount++;
                    Assert.AreEqual("Loaded", GetCurrentState(imageLoader));
                };

                imageLoader.Source = bitmapImage;

                Assert.AreEqual(1, imageOpendedCallCount, "{0} should only be called once", nameof(ImageEx.ImageExOpened));
            });
        }

        [TestMethod]
        [DataRow(ImageString)]
        [DataRow(@"ms-appx:///Assets/StoreLogo.png")]
        public async Task SetSourceToUri(string uri)
        {
            await App.DispatcherQueue.EnqueueAsync(async () =>
            {
                var imageLoader = new ImageEx();

                await SetTestContentAsync(imageLoader);

                Assert.AreEqual("Unloaded", GetCurrentState(imageLoader));

                var imageOpendedCallCount = 0;
                imageLoader.ImageExOpened += (s, e) =>
                {
                    imageOpendedCallCount++;
                    Assert.AreEqual("Loaded", GetCurrentState(imageLoader));
                };

                imageLoader.Source = new Uri(uri);

                // TODO (2021.05.11): Test in a more deterministic way.
                // Setting source causes some async code to trigger and
                // we have no way to await or handle its complementation regardless of the result.
                await Task.Delay(1000);
                Assert.AreEqual(1, imageOpendedCallCount, "{0} should only be called once", nameof(ImageEx.ImageExOpened));
            });
        }

        private static string GetCurrentState(ImageEx image)
            => VisualStateManager.GetVisualStateGroups(image.FindDescendant<Grid>()).First(g => g.Name == "CommonStates").CurrentState.Name;
    }
}